library(tidyverse)
## -- Attaching packages ------------------------------------------------------------------------------------------------ tidyverse 1.3.0 --
## v ggplot2 3.3.2 v purrr 0.3.4
## v tibble 3.0.3 v dplyr 1.0.2
## v tidyr 1.1.2 v stringr 1.4.0
## v readr 1.3.1 v forcats 0.5.0
## -- Conflicts --------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(magrittr)
##
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
##
## set_names
## The following object is masked from 'package:tidyr':
##
## extract
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(DT)
Parameters
DIST_METHOD = 'Manhattan'
errMethod = ifelse(DIST_METHOD == 'Manhattan','MSE','RMSE')
#weightFormula = function(x){ 1/(x)} #inverse of distance
weightFormula = function(x){ 1/(x ^ 2)} #inverse of sq distance
# Keep only required MAC Addresses
keepMacs = c(
#'00:0f:a3:39:e1:c0', #default
'00:0f:a3:39:dd:cd', #added
'00:14:bf:b1:97:8a',
'00:14:bf:3b:c7:c6',
'00:14:bf:b1:97:90',
'00:14:bf:b1:97:8d',
'00:14:bf:b1:97:81'
)
Files
offline_file = "../../data/offline.final.trace.txt"
online_file = "../../data/online.final.trace.txt"
Functions (Process Raw Data)
# Create a function to parse the data
processLine = function(x){
# Split up the line on ';', '=' and ','
tokens = strsplit(x, "[;=,]")[[1]]
# The hand held device (the one for which we need to determine the position)
# infromation is contained in the 1st 10 tokens (refer to book page 9)
# If no scanned signal values, return NULL
if (length(tokens) == 10) {
return(NULL)
}
# The tokens after the 10th one representthe signal strength at the access points (book page 9).
# Split up the tokens into individual measurements (each measurement contains 4 data points)
# 4 points are: MAC address, Signal, Channel and Device Type
# Device Type 3 is what is important (book page 6)
tmp = matrix(data = tokens[ - (1:10) ], ncol = 4, byrow = TRUE)
# Combine signal measurement with the h
cbind(matrix(tokens[c(2, 4, 6:8, 10)], nrow(tmp), 6, byrow = TRUE), tmp)
}
#' @description Function to read the data, clean it and process it into an appropriate format
#' @param file Filename to be read in
#' @param keepMacs a list of MAC addresses to keep
#' @returns A dataframe
readData = function(file, keepMacs=NULL){
# Read in the raw "offline" text file
txt = readLines(file)
##############################
#### Process the raw data ####
##############################
# Parse the data
lines = txt[substr(txt, 1, 1) != "#" ]
tmp = lapply(lines, processLine)
# Convert the data to a data frame
data = as.data.frame(do.call("rbind", tmp), stringsAsFactors = FALSE)
######################################################################
#### Cleaning the Data and Building a Representation for Analysis ####
######################################################################
# Assign column names to the offline data frame
names(data) = c(
"time", "scanMac", "posX", "posY", "posZ",
"orientation", "mac", "signal",
"channel", "type"
)
numVars = c("time", "posX", "posY", "posZ", "orientation", "signal")
data[numVars] = lapply(data[numVars], as.numeric)
# Keep only required device types (remove adhoc)
data = data[data$type != 1, ]
# Keep only required MAC Addresses
data = data[data$mac %in% keepMacs, ]
# # From book page 13
# data$rawTime = data$time
# data$time = data$time/1000
# class(data$time) = c("POSIXt", "POSIXct")
# Discard unwanted columns that dont add any additional information
data = data[ , !(names(data) %in% c("scanMac", "posZ"))]
# Cleanup Orientation
data$angle = roundOrientation(data$orientation)
# Add position identifier
data$posXY = paste(data$posX, data$posY, sep = "-")
return(data)
}
Offline data
numMacs = length(keepMacs)
numMacs
## [1] 6
roundOrientation = function(angles) {
refs = seq(0, by = 45, length = 9)
q = sapply(angles, function(o) which.min(abs(o - refs)))
c(refs[1:8], 0)[q]
}
offline = readData(file = offline_file, keepMacs = keepMacs)
dim(offline)
## [1] 769089 10
length(unique(offline$posXY))
## [1] 166
Online Data
online = readData(file = online_file, keepMacs = keepMacs)
dim(online)
## [1] 34815 10
length(unique(online$posXY))
## [1] 60
Function (Reshape)
# This is equivalent to the tall2wide function
reshapeSS = function(data, varSignal = "signal", keepVars = c("posXY", "posX", "posY"), sampleAngle = FALSE) {
refs = seq(0, by = 45, length = 8)
byLocation =
with(
data,
by(
data,
list(posXY),
function(x) {
if (sampleAngle) x = x[x$angle == sample(refs, size = 1), ]
ans = x[1, keepVars]
avgSS = tapply(x[ , varSignal ], x$mac, mean)
y = matrix(avgSS, nrow = 1, ncol = numMacs,
dimnames = list(ans$posXY, names(avgSS)))
cbind(ans, y)
}
)
)
newDataSS = do.call("rbind", byLocation)
return(newDataSS)
}
Reshape Test Data
keepVars = c("posXY", "posX","posY", "orientation", "angle")
onlineSummary = reshapeSS(data = online, varSignal = "signal", keepVars = keepVars)
onlineSummary
## posXY posX posY orientation angle 00:0f:a3:39:dd:cd
## 0-0.05 0-0.05 0.00 0.05 130.5 135 -63.20721
## 0.15-9.42 0.15-9.42 0.15 9.42 112.3 90 -66.11712
## 0.31-11.09 0.31-11.09 0.31 11.09 230.1 225 -67.05405
## 0.47-8.2 0.47-8.2 0.47 8.20 5.8 0 -74.15315
## 0.78-10.94 0.78-10.94 0.78 10.94 348.3 0 -71.40367
## 0.93-11.69 0.93-11.69 0.93 11.69 158.3 180 -69.99074
## 1.08-12.19 1.08-12.19 1.08 12.19 229.1 225 -73.43750
## 1.24-3.93 1.24-3.93 1.24 3.93 261.5 270 -71.11009
## 1.39-6.61 1.39-6.61 1.39 6.61 114.1 135 -59.75676
## 1.52-9.32 1.52-9.32 1.52 9.32 7.0 0 -65.38318
## 1.55-0.96 1.55-0.96 1.55 0.96 337.3 315 -68.06481
## 1.58-5.26 1.58-5.26 1.58 5.26 187.0 180 -72.07339
## 1.71-1.81 1.71-1.81 1.71 1.81 86.6 90 -65.53636
## 1.86-8.08 1.86-8.08 1.86 8.08 147.7 135 -66.53153
## 10.23-6.88 10.23-6.88 10.23 6.88 221.6 225 -57.65455
## 10.46-5.8 10.46-5.8 10.46 5.80 35.8 45 -64.97273
## 10.62-3.87 10.62-3.87 10.62 3.87 55.2 45 -66.50893
## 10.99-7.19 10.99-7.19 10.99 7.19 289.5 270 -61.03571
## 11.39-5 11.39-5 11.39 5.00 89.4 90 -64.31532
## 11.76-7.76 11.76-7.76 11.76 7.76 175.3 180 -65.19091
## 12.16-5.25 12.16-5.25 12.16 5.25 73.0 90 -69.20175
## 12.18-3.4 12.18-3.4 12.18 3.40 257.2 270 -64.99091
## 12.26-6.72 12.26-6.72 12.26 6.72 98.0 90 -57.22523
## 12.55-7.38 12.55-7.38 12.55 7.38 20.9 0 -59.17273
## 12.95-5.25 12.95-5.25 12.95 5.25 120.5 135 -72.74775
## 14.98-7.55 14.98-7.55 14.98 7.55 94.4 90 -65.28182
## 16.44-7.45 16.44-7.45 16.44 7.45 264.6 270 -68.76364
## 2.02-7.45 2.02-7.45 2.02 7.45 94.3 90 -63.12727
## 2.49-7.6 2.49-7.6 2.49 7.60 316.7 315 -69.53704
## 21.23-5.47 21.23-5.47 21.23 5.47 115.8 135 -80.01770
## 21.3-3.8 21.3-3.8 21.30 3.80 120.1 135 -77.18182
## 21.45-6.62 21.45-6.62 21.45 6.62 27.3 45 -71.63636
## 21.6-7.63 21.6-7.63 21.60 7.63 192.0 180 -75.20000
## 21.98-7.46 21.98-7.46 21.98 7.46 325.8 315 -66.56881
## 22.3-6.36 22.3-6.36 22.30 6.36 123.3 135 -79.35246
## 22.38-3.94 22.38-3.94 22.38 3.94 319.3 315 -75.38679
## 22.76-5.06 22.76-5.06 22.76 5.06 251.2 270 -82.71560
## 23.24-7.5 23.24-7.5 23.24 7.50 7.9 0 -79.59259
## 23.36-3.4 23.36-3.4 23.36 3.40 309.4 315 -73.18018
## 23.53-4.22 23.53-4.22 23.53 4.22 205.2 225 -78.27885
## 23.9-7 23.9-7 23.90 7.00 344.9 0 -78.04762
## 24.31-3.89 24.31-3.89 24.31 3.89 301.3 315 -75.68750
## 24.7-7.7 24.7-7.7 24.70 7.70 87.9 90 -76.44444
## 25.23-7.78 25.23-7.78 25.23 7.78 10.0 0 -75.52336
## 25.76-7.34 25.76-7.34 25.76 7.34 122.7 135 -79.20354
## 26.71-7.5 26.71-7.5 26.71 7.50 96.0 90 -75.63303
## 28.12-7.57 28.12-7.57 28.12 7.57 310.2 315 -78.03670
## 29.58-7.93 29.58-7.93 29.58 7.93 314.9 315 -84.16949
## 3.44-7.43 3.44-7.43 3.44 7.43 51.4 45 -62.51852
## 31.06-7.19 31.06-7.19 31.06 7.19 247.1 225 -80.55769
## 31.78-7.62 31.78-7.62 31.78 7.62 261.5 270 -78.10000
## 32.16-7.08 32.16-7.08 32.16 7.08 110.4 90 -82.54902
## 32.54-7.08 32.54-7.08 32.54 7.08 50.3 45 -79.44037
## 4.51-7.63 4.51-7.63 4.51 7.63 330.5 315 -64.36364
## 6-7.88 6-7.88 6.00 7.88 137.0 135 -66.05405
## 7.48-7.36 7.48-7.36 7.48 7.36 340.1 0 -62.77477
## 8.56-7.64 8.56-7.64 8.56 7.64 305.1 315 -54.33333
## 9.08-7.24 9.08-7.24 9.08 7.24 338.0 0 -55.54867
## 9.46-7.77 9.46-7.77 9.46 7.77 169.4 180 -61.36697
## 9.86-3.88 9.86-3.88 9.86 3.88 191.1 180 -65.50000
## 00:14:bf:3b:c7:c6 00:14:bf:b1:97:81 00:14:bf:b1:97:8a
## 0-0.05 -62.94898 -61.81395 -40.06897
## 0.15-9.42 -73.96190 -72.70103 -47.81308
## 0.31-11.09 -70.08247 -70.09890 -54.08824
## 0.47-8.2 -64.25806 -72.59770 -45.65289
## 0.78-10.94 -66.96000 -66.80952 -48.41379
## 0.93-11.69 -70.44340 -70.58025 -43.66346
## 1.08-12.19 -69.20192 -67.92553 -52.00820
## 1.24-3.93 -69.62745 -59.76136 -38.91753
## 1.39-6.61 -62.23913 -64.56627 -48.92381
## 1.52-9.32 -63.35922 -67.48913 -50.04167
## 1.55-0.96 -66.08989 -57.69318 -42.99038
## 1.58-5.26 -64.66667 -57.42708 -40.50980
## 1.71-1.81 -61.75789 -66.12088 -37.01000
## 1.86-8.08 -62.06383 -63.03571 -50.58252
## 10.23-6.88 -58.29474 -59.21348 -58.57143
## 10.46-5.8 -52.60241 -57.57895 -58.17204
## 10.62-3.87 -45.98039 -46.01111 -59.38333
## 10.99-7.19 -49.81633 -56.66292 -56.38739
## 11.39-5 -48.89011 -59.76404 -58.79048
## 11.76-7.76 -54.76768 -59.32967 -57.10891
## 12.16-5.25 -49.90361 -59.13415 -52.58621
## 12.18-3.4 -45.47727 -55.19149 -59.09574
## 12.26-6.72 -50.56180 -58.85393 -56.63636
## 12.55-7.38 -52.32941 -58.08791 -62.24038
## 12.95-5.25 -47.92929 -56.78161 -57.38261
## 14.98-7.55 -53.54902 -53.06122 -66.53659
## 16.44-7.45 -58.18824 -52.74725 -58.28261
## 2.02-7.45 -66.21212 -66.16667 -48.09346
## 2.49-7.6 -65.31522 -67.35955 -43.86111
## 21.23-5.47 -62.32653 -50.75000 -62.22105
## 21.3-3.8 -61.67816 -44.22222 -67.09278
## 21.45-6.62 -60.32927 -49.98667 -60.42857
## 21.6-7.63 -61.39773 -52.94186 -72.88043
## 21.98-7.46 -61.76667 -53.83696 -60.47863
## 22.3-6.36 -60.09091 -51.77907 -64.20652
## 22.38-3.94 -61.15116 -52.61798 -58.39535
## 22.76-5.06 -61.07609 -53.14737 -61.75269
## 23.24-7.5 -59.52874 -53.79348 -65.22772
## 23.36-3.4 -57.63830 -53.00000 -54.15741
## 23.53-4.22 -63.76136 -50.84706 -56.97753
## 23.9-7 -61.65556 -54.16495 -64.83333
## 24.31-3.89 -58.11702 -52.49451 -65.45652
## 24.7-7.7 -63.43478 -56.61538 -70.97000
## 25.23-7.78 -66.38144 -53.67033 -67.12745
## 25.76-7.34 -68.34409 -52.56818 -63.50000
## 26.71-7.5 -66.93827 -48.82979 -68.05556
## 28.12-7.57 -64.30693 -53.96739 -68.77551
## 29.58-7.93 -69.32143 -48.34737 -68.84000
## 3.44-7.43 -63.43333 -62.39535 -51.42857
## 31.06-7.19 -70.86585 -45.40860 -62.20652
## 31.78-7.62 -65.65625 -49.38824 -65.94574
## 32.16-7.08 -70.26471 -44.57303 -69.33621
## 32.54-7.08 -64.98913 -53.78261 -68.54639
## 4.51-7.63 -65.48485 -65.15217 -50.73134
## 6-7.88 -57.37634 -58.78481 -51.07000
## 7.48-7.36 -59.63158 -61.59574 -52.70642
## 8.56-7.64 -53.83133 -61.20652 -55.89320
## 9.08-7.24 -53.66667 -58.09639 -59.20652
## 9.46-7.77 -49.64516 -61.18824 -60.80851
## 9.86-3.88 -44.13131 -52.63333 -55.94000
## 00:14:bf:b1:97:8d 00:14:bf:b1:97:90
## 0-0.05 -63.04301 -55.23333
## 0.15-9.42 -69.45455 -46.88000
## 0.31-11.09 -69.13158 -53.88660
## 0.47-8.2 -60.79747 -49.58000
## 0.78-10.94 -65.00000 -54.84694
## 0.93-11.69 -65.59302 -47.27083
## 1.08-12.19 -71.58696 -51.66667
## 1.24-3.93 -71.66667 -53.23333
## 1.39-6.61 -60.79798 -50.49057
## 1.52-9.32 -65.10345 -49.38542
## 1.55-0.96 -63.52632 -50.04000
## 1.58-5.26 -61.97778 -62.48913
## 1.71-1.81 -64.33721 -53.21359
## 1.86-8.08 -51.38462 -49.96078
## 10.23-6.88 -50.10417 -67.56098
## 10.46-5.8 -58.74444 -65.31111
## 10.62-3.87 -61.26582 -68.40909
## 10.99-7.19 -55.78161 -66.21429
## 11.39-5 -58.35789 -74.37079
## 11.76-7.76 -54.22549 -67.06796
## 12.16-5.25 -56.73469 -67.09877
## 12.18-3.4 -60.80851 -76.48864
## 12.26-6.72 -46.17708 -68.72449
## 12.55-7.38 -51.67327 -68.34940
## 12.95-5.25 -58.03191 -69.42857
## 14.98-7.55 -44.18085 -77.11111
## 16.44-7.45 -45.52222 -68.65934
## 2.02-7.45 -57.96703 -58.68817
## 2.49-7.6 -62.64444 -44.71698
## 21.23-5.47 -50.95506 -79.14130
## 21.3-3.8 -56.42222 -78.50459
## 21.45-6.62 -41.11364 -70.95181
## 21.6-7.63 -50.27473 -80.23913
## 21.98-7.46 -52.13978 -76.55422
## 22.3-6.36 -47.46739 -77.80460
## 22.38-3.94 -49.43678 -73.38636
## 22.76-5.06 -49.97917 -76.54444
## 23.24-7.5 -56.66316 -69.67391
## 23.36-3.4 -54.28736 -73.41860
## 23.53-4.22 -55.40698 -78.16092
## 23.9-7 -58.33735 -69.24468
## 24.31-3.89 -54.35000 -78.72449
## 24.7-7.7 -44.89011 -75.44318
## 25.23-7.78 -47.34694 -73.71277
## 25.76-7.34 -45.03297 -77.07447
## 26.71-7.5 -47.25243 -75.80460
## 28.12-7.57 -53.68421 -70.62000
## 29.58-7.93 -49.95745 -75.66667
## 3.44-7.43 -52.05941 -60.35484
## 31.06-7.19 -39.36264 -79.72619
## 31.78-7.62 -45.44944 -76.68932
## 32.16-7.08 -37.55340 -77.05600
## 32.54-7.08 -32.84946 -71.63953
## 4.51-7.63 -62.29268 -60.14851
## 6-7.88 -54.40000 -61.91667
## 7.48-7.36 -59.89362 -63.77528
## 8.56-7.64 -56.65217 -66.17021
## 9.08-7.24 -57.08434 -65.36364
## 9.46-7.77 -49.34118 -71.44737
## 9.86-3.88 -55.94937 -65.53261
Function (Select Train Data)
#' @description Selectes the appropriate observations (based on test data orientation) from the original tall data
#' and reformats it such that it can be used for training the KNN algorithm
#' @param angleNewObs Angle (Orientation) of the test observation
#' @param train_data Original tall-skinny data
#' @param m Keep the 'm' closest orientations to angleNewObs
#' @returns A dataframe suitable for training
selectTrain = function(angleNewObs, train_data, m){
# Find the angles to keep
nearestAngle = roundOrientation(angles = angleNewObs)
if (m %% 2 == 1) {
angles = seq(-45 * (m - 1) /2, 45 * (m - 1) /2, length = m)
} else {
m = m + 1
angles = seq(-45 * (m - 1) /2, 45 * (m - 1) /2, length = m)
if (sign(angleNewObs - nearestAngle) > -1)
angles = angles[ -1 ]
else
angles = angles[ -m ]
}
angles = angles + nearestAngle
angles[angles < 0] = angles[ angles < 0 ] + 360
angles[angles > 360] = angles[ angles > 360 ] - 360
# Subset only those angles from original data (tall-skinny)
train_data_subset = train_data[train_data$angle %in% angles, ]
# Convert to Wide and average the data for the same positions
train_data_subset = reshapeSS(data = train_data_subset, varSignal = "signal")
return(train_data_subset)
}
Nearest Neighbors
Common Functions
#' @description Computes the distance of the new signal (single observation) to each observation in the training dataset
#' @param newSignals The Signal Values for the validation data for each observation
#' @param trainSubset The training data to be used
#' @param weighted Whether the mean value should be weighted based on distancde or not.
#' @return A dataframe containing same number of rows as that in the training data.
#' The observations are ordered by the distance to the new signal. Each row contains 5 columns.
#' 1st column is the XY location of the training observation (string)
#' 2nd column is the X location of the training observation (float)
#' 3rd column is the Y location of the training observation (float)
#' 4th column is the distance to the point under consideration to the training observation (float)
#' 5th column is the inverse distance or weight (float). Weight is hard coded to 1 for all observations if weighted = FALSE
findNN = function(newSignal, trainSubset, weighted=FALSE, method = DIST_METHOD) {
diffs = apply(trainSubset[ , 4:(4+numMacs-1)], 1, function(x) x - newSignal)
if(method=='Euclidian') dists = apply(diffs, 2, function(x) sqrt(sum(x^2)) ) #RSE
if(method=='Manhattan') dists = apply(diffs, 2, function(x) sum(abs(x)) ) #AE
closest = order(dists)
ordered_dist = dists[closest]
if(weighted == TRUE){
weight = weightFormula(ordered_dist)
}
if(weighted == FALSE){
weight = rep(1, length(dists))
}
return(cbind(trainSubset[closest, 1:3], ordered_dist, weight))
}
#' @description XY Prediction for a single value of k (num neighbors)
#' @param newSignals The Signal Values for the validation data for each observation
#' @param newAngles The Orientation of the validation data for each observation
#' @param trainData The training data to be used
#' @param numAngles Number of closest reference angles to include in the data
#' @param k Perform the predicton for num neighbors = k
#' @param weighted Whether the mean value should be weighted based on distancde or not.
#' @return A dataframe with num rows = number of (validation) observations and num columns = 2
#' Each row indicates the prediction of the mean X and Y values for that observation
predXY = function(newSignals, newAngles, trainData, numAngles = 1, k = 3, weighted=FALSE){
closeXY = list(length = nrow(newSignals))
for (i in 1:nrow(newSignals)) {
trainSS = selectTrain(newAngles[i], trainData, m = numAngles)
closeXY[[i]] = findNN(
newSignal = as.numeric(newSignals[i, ]),
trainSubset = trainSS,
weighted = weighted
)
}
#' @description Returns the (un)weighted mean X and Y locations for a single observation and single value of neighbors
#' @param x Dataframe containing 5 columns
#' 1st column is the XY location (string)
#' 2nd column is the X location (float)
#' 3rd column is the Y location (float)
#' 4th column is the distance to the point under consideration (float)
#' 5th column is the inverse distance or weight (float)
#' @param k Number of nearest neighbors to use
#' @return A pair of XY mean values for k number of neighbors
k_means_single_obs = function(x, k){
weights = x[1:k, 5]
weighted_x = sum(x[1:k, 2] * weights) / sum(weights)
weighted_y = sum(x[1:k, 3] * weights) / sum(weights)
return(c(weighted_x, weighted_y))
}
# estXY = lapply(closeXY, function(x) sapply(x[ , 2:3], function(x) mean(x[1:k])))
estXY = lapply(closeXY, k_means_single_obs, k)
estXY = do.call("rbind", estXY)
return(estXY)
}
calcError = function(estXY, actualXY, method = DIST_METHOD){
if('numeric' %in% class(estXY)) rows = 1 else rows = nrow(estXY)
if(method == 'Euclidean') er = sqrt(sum(rowSums((estXY - actualXY)^2)))/rows
if(method == 'Manhattan') er = sum(rowSums(abs(estXY - actualXY)))/rows
return(er)
}
K-Fold
Setup
set.seed(42)
K = 20
v = 11
allNeighbors = c(1:K)
allNeighbors
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
allAngles = c(1:8)
allAngles
## [1] 1 2 3 4 5 6 7 8
permuteLocs = sample(unique(offline$posXY))
permuteLocs = matrix(permuteLocs, ncol = v, nrow = floor(length(permuteLocs)/v))
## Warning in matrix(permuteLocs, ncol = v, nrow = floor(length(permuteLocs)/v)):
## data length [166] is not a sub-multiple or multiple of the number of rows [15]
permuteLocs
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] "11-3" "24-6" "27-8" "25-8" "7-7" "24-8" "22-8" "12-5" "0-12" "0-7"
## [2,] "9-7" "21-6" "2-9" "24-7" "5-8" "15-8" "11-8" "32-6" "2-7" "29-8"
## [3,] "14-7" "30-3" "12-7" "23-4" "2-2" "10-5" "4-7" "17-8" "0-11" "17-7"
## [4,] "13-8" "3-3" "32-8" "30-7" "2-8" "33-7" "25-3" "1-13" "12-6" "24-3"
## [5,] "33-8" "15-7" "30-8" "0-3" "20-3" "21-3" "2-11" "13-3" "8-8" "22-3"
## [6,] "21-8" "0-8" "0-1" "2-13" "1-5" "0-4" "0-0" "23-3" "1-10" "16-8"
## [7,] "20-8" "24-5" "26-3" "31-8" "31-3" "10-4" "3-8" "2-5" "8-7" "0-9"
## [8,] "27-3" "1-1" "32-3" "2-6" "13-7" "11-4" "26-6" "8-3" "26-4" "1-3"
## [9,] "9-3" "19-3" "2-1" "14-8" "33-4" "6-8" "5-7" "1-4" "13-6" "4-8"
## [10,] "1-12" "25-4" "20-7" "24-4" "26-7" "0-13" "22-4" "19-7" "33-3" "18-8"
## [11,] "10-8" "2-0" "1-0" "16-7" "7-8" "3-7" "6-7" "26-8" "2-4" "32-5"
## [12,] "21-4" "11-5" "21-7" "27-7" "32-7" "13-5" "15-3" "9-4" "7-3" "22-7"
## [13,] "16-3" "4-3" "28-8" "21-5" "1-6" "22-5" "19-8" "10-7" "1-11" "25-7"
## [14,] "26-5" "18-7" "23-7" "12-8" "29-3" "23-5" "13-4" "2-10" "2-3" "10-3"
## [15,] "1-8" "5-3" "1-9" "0-10" "12-4" "31-7" "28-3" "11-7" "23-6" "28-7"
## [,11]
## [1,] "10-6"
## [2,] "1-7"
## [3,] "23-8"
## [4,] "11-6"
## [5,] "14-3"
## [6,] "12-3"
## [7,] "29-7"
## [8,] "22-6"
## [9,] "18-3"
## [10,] "17-3"
## [11,] "9-8"
## [12,] "6-3"
## [13,] "32-4"
## [14,] "0-2"
## [15,] "1-2"
onlineFold = subset(offline, posXY %in% permuteLocs[ , 1])
head(onlineFold)
## time posX posY orientation mac signal channel
## 154732 1.139653e+12 1 8 0.7 00:14:bf:b1:97:8a -47 2437000000
## 154733 1.139653e+12 1 8 0.7 00:14:bf:b1:97:8d -52 2442000000
## 154735 1.139653e+12 1 8 0.7 00:14:bf:b1:97:90 -51 2427000000
## 154736 1.139653e+12 1 8 0.7 00:14:bf:3b:c7:c6 -68 2432000000
## 154737 1.139653e+12 1 8 0.7 00:14:bf:b1:97:81 -67 2422000000
## 154738 1.139653e+12 1 8 0.7 00:0f:a3:39:dd:cd -72 2412000000
## type angle posXY
## 154732 3 0 1-8
## 154733 3 0 1-8
## 154735 3 0 1-8
## 154736 3 0 1-8
## 154737 3 0 1-8
## 154738 3 0 1-8
# For reference
head(onlineSummary)
## posXY posX posY orientation angle 00:0f:a3:39:dd:cd
## 0-0.05 0-0.05 0.00 0.05 130.5 135 -63.20721
## 0.15-9.42 0.15-9.42 0.15 9.42 112.3 90 -66.11712
## 0.31-11.09 0.31-11.09 0.31 11.09 230.1 225 -67.05405
## 0.47-8.2 0.47-8.2 0.47 8.20 5.8 0 -74.15315
## 0.78-10.94 0.78-10.94 0.78 10.94 348.3 0 -71.40367
## 0.93-11.69 0.93-11.69 0.93 11.69 158.3 180 -69.99074
## 00:14:bf:3b:c7:c6 00:14:bf:b1:97:81 00:14:bf:b1:97:8a
## 0-0.05 -62.94898 -61.81395 -40.06897
## 0.15-9.42 -73.96190 -72.70103 -47.81308
## 0.31-11.09 -70.08247 -70.09890 -54.08824
## 0.47-8.2 -64.25806 -72.59770 -45.65289
## 0.78-10.94 -66.96000 -66.80952 -48.41379
## 0.93-11.69 -70.44340 -70.58025 -43.66346
## 00:14:bf:b1:97:8d 00:14:bf:b1:97:90
## 0-0.05 -63.04301 -55.23333
## 0.15-9.42 -69.45455 -46.88000
## 0.31-11.09 -69.13158 -53.88660
## 0.47-8.2 -60.79747 -49.58000
## 0.78-10.94 -65.00000 -54.84694
## 0.93-11.69 -65.59302 -47.27083
keepVars = c("posXY", "posX","posY", "orientation", "angle")
onlineCVSummary = reshapeSS(offline, keepVars = keepVars, sampleAngle = TRUE)
onlineCVSummary
## posXY posX posY orientation angle 00:0f:a3:39:dd:cd 00:14:bf:3b:c7:c6
## 0-0 0-0 0 0 90.3 90 -73.96330 -62.59551
## 0-1 0-1 0 1 89.8 90 -70.44144 -65.70000
## 0-10 0-10 0 10 225.3 225 -66.80357 -63.01163
## 0-11 0-11 0 11 135.2 135 -69.40541 -67.87778
## 0-12 0-12 0 12 135.0 135 -68.57273 -68.90816
## 0-13 0-13 0 13 135.2 135 -73.68750 -71.76190
## 0-2 0-2 0 2 90.3 90 -71.31532 -61.17000
## 0-3 0-3 0 3 0.2 0 -69.09649 -62.90526
## 0-4 0-4 0 4 0.5 0 -68.94643 -65.86139
## 0-7 0-7 0 7 0.3 0 -71.43636 -65.85417
## 0-8 0-8 0 8 225.0 225 -63.85714 -65.64583
## 0-9 0-9 0 9 180.2 180 -66.59459 -66.60000
## 1-0 1-0 1 0 269.7 270 -69.97297 -62.85556
## 1-1 1-1 1 1 225.2 225 -69.86239 -67.75532
## 1-10 1-10 1 10 135.4 135 -66.30000 -68.70833
## 1-11 1-11 1 11 269.8 270 -67.00000 -69.07609
## 1-12 1-12 1 12 359.9 0 -71.78182 -67.88785
## 1-13 1-13 1 13 180.3 180 -69.78571 -69.90909
## 1-2 1-2 1 2 134.4 135 -63.38393 -62.31183
## 1-3 1-3 1 3 0.2 0 -74.08036 -61.19318
## 1-4 1-4 1 4 0.8 0 -67.14414 -62.98925
## 1-5 1-5 1 5 0.3 0 -66.86607 -69.08411
## 1-6 1-6 1 6 135.4 135 -66.44144 -63.47253
## 1-7 1-7 1 7 45.3 45 -71.07339 -69.16484
## 1-8 1-8 1 8 270.2 270 -69.76364 -65.55435
## 1-9 1-9 1 9 315.1 315 -67.14159 -63.67021
## 10-3 10-3 10 3 270.4 270 -69.49107 -55.84043
## 10-4 10-4 10 4 314.8 315 -72.00952 -54.46000
## 10-5 10-5 10 5 90.3 90 -64.30973 -50.66667
## 10-6 10-6 10 6 180.8 180 -66.18919 -54.15054
## 10-7 10-7 10 7 180.3 180 -57.61818 -53.31868
## 10-8 10-8 10 8 135.1 135 -61.20909 -57.16327
## 11-3 11-3 11 3 359.9 0 -63.09910 -54.42857
## 11-4 11-4 11 4 224.8 225 -64.86364 -52.89899
## 11-5 11-5 11 5 89.8 90 -61.82727 -51.30682
## 11-6 11-6 11 6 134.8 135 -61.90909 -50.55208
## 11-7 11-7 11 7 270.2 270 -58.13761 -46.47778
## 11-8 11-8 11 8 180.3 180 -67.70909 -54.81553
## 12-3 12-3 12 3 269.6 270 -63.96364 -39.25490
## 12-4 12-4 12 4 315.1 315 -65.80180 -49.19101
## 12-5 12-5 12 5 224.8 225 -66.71681 -52.77647
## 12-6 12-6 12 6 270.5 270 -65.81818 -47.44706
## 12-7 12-7 12 7 315.1 315 -60.21818 -53.56322
## 12-8 12-8 12 8 45.3 45 -58.42202 -59.33333
## 13-3 13-3 13 3 270.6 270 -66.90909 -52.49451
## 13-4 13-4 13 4 270.2 270 -73.06195 -49.82955
## 13-5 13-5 13 5 0.7 0 -65.94118 -48.21348
## 13-6 13-6 13 6 0.1 0 -58.48182 -50.34000
## 13-7 13-7 13 7 0.3 0 -59.53571 -50.15730
## 13-8 13-8 13 8 90.3 90 -65.99115 -57.77174
## 14-3 14-3 14 3 46.5 45 -69.11215 -56.63265
## 14-7 14-7 14 7 180.2 180 -69.66972 -58.02273
## 14-8 14-8 14 8 270.1 270 -60.39450 -43.11881
## 15-3 15-3 15 3 134.9 135 -75.23636 -58.57576
## 15-7 15-7 15 7 135.4 135 -67.97273 -56.77419
## 15-8 15-8 15 8 270.4 270 -58.11712 -52.25000
## 16-3 16-3 16 3 180.4 180 -67.57273 -61.24138
## 16-7 16-7 16 7 0.4 0 -57.97273 -57.52688
## 16-8 16-8 16 8 134.9 135 -75.38532 -46.62366
## 17-3 17-3 17 3 1.0 0 -72.88991 -52.52809
## 17-7 17-7 17 7 316.0 315 -72.83636 -57.50515
## 17-8 17-8 17 8 225.7 225 -71.23636 -57.16279
## 18-3 18-3 18 3 315.7 315 -75.11818 -53.55882
## 18-7 18-7 18 7 0.4 0 -70.91818 -57.64286
## 18-8 18-8 18 8 180.5 180 -64.40000 -62.86957
## 19-3 19-3 19 3 225.2 225 -75.83636 -57.71429
## 19-7 19-7 19 7 89.5 90 -73.75229 -60.02083
## 19-8 19-8 19 8 359.9 0 -67.45872 -55.48980
## 2-0 2-0 2 0 225.0 225 -69.38182 -62.38144
## 2-1 2-1 2 1 45.6 45 -73.94595 -63.75238
## 2-10 2-10 2 10 226.5 225 -63.30909 -63.50575
## 2-11 2-11 2 11 225.7 225 -65.12613 -70.28571
## 2-12 2-12 2 12 136.7 135 -73.79091 -72.46602
## 2-13 2-13 2 13 270.9 270 -70.50000 -64.84685
## 2-2 2-2 2 2 225.4 225 -69.36937 -63.31579
## 2-3 2-3 2 3 270.5 270 -71.73451 -64.38542
## 2-4 2-4 2 4 44.4 45 -62.93636 -60.48276
## 2-5 2-5 2 5 180.4 180 -67.82143 -64.64444
## 2-6 2-6 2 6 180.3 180 -67.12613 -61.84270
## 2-7 2-7 2 7 90.3 90 -64.59091 -65.40385
## 2-8 2-8 2 8 270.4 270 -62.17117 -65.40230
## 2-9 2-9 2 9 180.1 180 -67.59813 -64.81308
## 20-3 20-3 20 3 45.2 45 -71.32110 -57.86022
## 20-7 20-7 20 7 1.5 0 -63.80000 -65.09890
## 20-8 20-8 20 8 225.6 225 -75.78182 -59.83158
## 21-3 21-3 21 3 0.1 0 -75.51376 -61.45455
## 21-4 21-4 21 4 225.0 225 -76.40000 -63.62500
## 21-5 21-5 21 5 315.4 315 -79.87273 -61.23958
## 21-6 21-6 21 6 0.0 0 -72.71171 -64.68817
## 21-7 21-7 21 7 90.4 90 -73.80357 -64.82653
## 21-8 21-8 21 8 135.5 135 -76.44954 -63.71717
## 22-3 22-3 22 3 45.1 45 -77.17431 -60.08989
## 22-4 22-4 22 4 270.2 270 -80.91743 -56.65306
## 22-5 22-5 22 5 45.3 45 -75.72727 -59.72941
## 22-6 22-6 22 6 45.6 45 -76.15455 -61.73913
## 22-7 22-7 22 7 44.8 45 -64.09009 -65.75789
## 22-8 22-8 22 8 135.4 135 -75.33636 -67.57009
## 23-3 23-3 23 3 135.1 135 -84.19626 -59.45000
## 23-4 23-4 23 4 270.6 270 -78.44545 -59.74737
## 23-5 23-5 23 5 180.0 180 -81.85437 -60.76087
## 23-6 23-6 23 6 270.2 270 -77.33945 -62.09375
## 23-7 23-7 23 7 359.6 0 -75.12727 -59.80769
## 23-8 23-8 23 8 90.0 90 -73.90826 -62.66316
## 24-3 24-3 24 3 224.9 225 -80.17431 -62.89796
## 24-4 24-4 24 4 180.5 180 -81.35514 -60.77174
## 24-5 24-5 24 5 225.2 225 -74.43119 -59.80000
## 24-6 24-6 24 6 135.3 135 -76.00909 -66.41284
## 24-7 24-7 24 7 45.1 45 -75.98165 -60.71910
## 24-8 24-8 24 8 44.7 45 -73.90909 -66.20388
## 25-3 25-3 25 3 0.0 0 -77.86239 -59.21505
## 25-4 25-4 25 4 90.6 90 -82.92424 -63.05102
## 25-7 25-7 25 7 134.9 135 -77.06542 -65.80851
## 25-8 25-8 25 8 225.3 225 -80.30909 -63.98864
## 26-3 26-3 26 3 45.4 45 -78.48148 -60.44211
## 26-4 26-4 26 4 359.8 0 -77.01905 -63.26214
## 26-5 26-5 26 5 270.5 270 -76.07339 -57.17978
## 26-6 26-6 26 6 270.5 270 -76.36937 -59.74468
## 26-7 26-7 26 7 45.2 45 -74.86364 -59.42105
## 26-8 26-8 26 8 89.9 90 -78.44144 -64.29897
## 27-3 27-3 27 3 0.2 0 -76.67273 -61.33333
## 27-7 27-7 27 7 90.0 90 -78.51961 -66.15730
## 27-8 27-8 27 8 90.6 90 -77.16364 -65.46067
## 28-3 28-3 28 3 135.2 135 -81.78723 -62.39286
## 28-7 28-7 28 7 180.4 180 -80.60377 -69.10989
## 28-8 28-8 28 8 135.1 135 -77.45045 -70.12121
## 29-3 29-3 29 3 44.7 45 -80.29091 -64.51546
## 29-7 29-7 29 7 225.1 225 -81.56250 -67.22772
## 29-8 29-8 29 8 0.2 0 -78.79091 -62.17476
## 3-3 3-3 3 3 225.7 225 -62.62385 -56.77451
## 3-7 3-7 3 7 89.2 90 -58.76364 -62.98980
## 3-8 3-8 3 8 358.3 0 -65.36697 -66.09677
## 30-3 30-3 30 3 225.6 225 -82.82569 -64.67391
## 30-7 30-7 30 7 91.5 90 -72.74312 -62.55914
## 30-8 30-8 30 8 180.1 180 -80.94186 -63.29474
## 31-3 31-3 31 3 135.5 135 -83.03774 -71.11765
## 31-7 31-7 31 7 180.4 180 -79.19266 -69.27885
## 31-8 31-8 31 8 224.6 225 -76.36697 -67.87387
## 32-3 32-3 32 3 270.4 270 -85.44545 -65.91818
## 32-4 32-4 32 4 0.5 0 -78.33636 -62.71000
## 32-5 32-5 32 5 44.2 45 -81.33913 -72.29703
## 32-6 32-6 32 6 314.8 315 -85.82400 -75.97321
## 32-7 32-7 32 7 45.2 45 -78.97248 -59.64130
## 32-8 32-8 32 8 270.9 270 -76.64545 -68.27723
## 33-3 33-3 33 3 269.7 270 -79.39604 -71.03750
## 33-4 33-4 33 4 225.7 225 -82.17593 -65.54545
## 33-7 33-7 33 7 135.1 135 -83.88679 -74.52830
## 33-8 33-8 33 8 179.6 180 -75.18519 -70.86139
## 4-3 4-3 4 3 90.3 90 -58.60185 -58.90909
## 4-7 4-7 4 7 45.9 45 -62.80180 -60.31250
## 4-8 4-8 4 8 359.6 0 -65.86486 -66.79570
## 5-3 5-3 5 3 359.9 0 -70.09091 -56.02273
## 5-7 5-7 5 7 180.5 180 -58.59633 -58.48936
## 5-8 5-8 5 8 45.8 45 -59.38739 -62.12500
## 6-3 6-3 6 3 90.4 90 -56.87156 -55.97917
## 6-7 6-7 6 7 45.2 45 -58.48624 -61.62766
## 6-8 6-8 6 8 91.5 90 -54.96429 -57.75248
## 7-3 7-3 7 3 225.0 225 -60.88991 -53.18478
## 7-7 7-7 7 7 271.5 270 -59.80531 -56.10112
## 7-8 7-8 7 8 91.0 90 -57.20909 -54.45000
## 8-3 8-3 8 3 315.5 315 -60.65766 -53.97778
## 8-7 8-7 8 7 135.6 135 -56.46903 -56.15789
## 8-8 8-8 8 8 315.4 315 -52.48624 -55.73626
## 9-3 9-3 9 3 179.8 180 -60.72477 -50.36957
## 9-4 9-4 9 4 315.0 315 -61.11927 -55.13095
## 9-7 9-7 9 7 225.7 225 -55.43243 -50.96591
## 9-8 9-8 9 8 134.8 135 -51.39815 -53.21875
## 00:14:bf:b1:97:81 00:14:bf:b1:97:8a 00:14:bf:b1:97:8d 00:14:bf:b1:97:90
## 0-0 -63.78261 -33.74737 -63.12941 -55.19588
## 0-1 -63.94186 -40.21782 -63.52381 -60.47826
## 0-10 -68.58416 -49.01010 -66.71111 -54.56180
## 0-11 -72.34000 -47.57895 -66.17241 -53.97000
## 0-12 -70.32222 -43.11009 -63.73494 -48.99000
## 0-13 -74.19588 -42.49438 -67.70423 -50.82828
## 0-2 -61.43333 -45.52000 -58.31461 -51.36364
## 0-3 -56.68817 -49.96040 -59.29412 -55.37755
## 0-4 -57.21111 -47.65591 -65.46154 -52.17000
## 0-7 -65.92632 -45.79439 -55.21111 -61.61798
## 0-8 -58.03750 -47.52830 -47.47674 -57.93878
## 0-9 -63.39286 -43.18367 -58.92045 -48.58763
## 1-0 -70.71429 -34.42424 -65.59770 -57.18182
## 1-1 -60.85263 -33.97980 -63.91753 -59.78846
## 1-10 -71.59091 -43.90741 -64.37500 -52.82653
## 1-11 -71.31111 -46.50000 -65.74118 -52.92784
## 1-12 -71.93617 -42.65979 -63.21978 -44.97872
## 1-13 -74.17204 -41.90625 -67.74468 -48.67677
## 1-2 -63.29545 -36.15238 -62.52688 -56.79787
## 1-3 -57.52273 -39.57547 -59.28049 -55.08333
## 1-4 -61.50538 -44.34000 -59.68085 -57.43011
## 1-5 -64.28235 -45.12766 -62.32468 -56.72826
## 1-6 -66.38824 -47.38776 -60.62500 -52.45361
## 1-7 -65.28916 -45.30097 -50.42857 -53.81633
## 1-8 -59.13793 -50.12766 -49.57143 -55.23469
## 1-9 -60.80435 -40.73832 -63.00000 -53.02299
## 10-3 -56.19417 -47.72477 -56.34694 -72.47619
## 10-4 -60.08602 -53.26168 -59.57778 -66.38298
## 10-5 -56.93407 -58.00000 -60.55056 -71.17442
## 10-6 -57.55952 -58.36752 -57.10989 -61.78218
## 10-7 -63.63218 -59.81443 -51.74725 -73.09574
## 10-8 -59.56122 -58.85149 -53.18000 -67.21429
## 11-3 -53.75000 -52.00926 -62.31707 -70.51685
## 11-4 -48.91860 -52.80769 -58.63529 -69.65000
## 11-5 -66.76829 -59.94697 -60.42857 -72.97938
## 11-6 -62.44444 -55.67213 -56.32184 -70.55660
## 11-7 -59.56790 -57.37755 -52.48837 -69.86170
## 11-8 -59.52083 -59.10256 -45.60000 -69.75269
## 12-3 -56.00000 -58.23810 -60.25287 -71.31868
## 12-4 -56.77381 -59.38686 -63.05263 -67.76699
## 12-5 -56.55814 -55.43860 -56.95098 -63.83696
## 12-6 -61.73256 -56.95699 -57.35484 -73.57471
## 12-7 -54.39326 -56.39496 -56.43678 -66.40860
## 12-8 -56.51064 -53.31250 -48.84000 -74.35955
## 13-3 -58.59302 -57.98198 -61.26506 -72.36986
## 13-4 -57.12791 -53.10526 -57.68182 -72.30337
## 13-5 -57.91765 -53.27551 -60.67778 -65.64198
## 13-6 -59.35556 -57.98131 -59.33000 -68.91304
## 13-7 -62.71429 -59.75630 -56.50000 -68.07527
## 13-8 -62.31313 -58.43000 -53.05495 -64.02198
## 14-3 -49.15625 -59.57778 -54.42391 -69.14423
## 14-7 -57.19318 -58.09278 -37.25000 -67.87209
## 14-8 -62.00000 -51.69149 -53.34884 -65.96386
## 15-3 -48.31395 -57.06250 -56.70588 -68.55556
## 15-7 -55.67708 -63.58696 -46.53571 -67.48000
## 15-8 -62.54430 -51.27473 -57.02970 -60.87000
## 16-3 -44.92708 -65.02299 -56.13636 -73.07071
## 16-7 -55.59091 -58.27835 -51.92000 -75.81720
## 16-8 -59.33929 -58.20833 -46.65909 -75.87179
## 17-3 -55.28866 -61.97778 -56.55670 -75.63953
## 17-7 -56.80198 -54.44211 -46.64646 -67.81609
## 17-8 -50.87778 -59.34884 -53.41304 -70.77419
## 18-3 -54.85106 -63.91304 -57.83333 -71.76344
## 18-7 -57.38043 -62.67442 -49.17857 -72.95604
## 18-8 -58.51136 -57.26733 -44.74000 -75.96552
## 19-3 -49.63953 -58.00000 -57.71277 -77.38095
## 19-7 -57.39130 -57.51064 -49.92708 -76.04255
## 19-8 -56.39326 -59.41111 -52.65556 -68.78409
## 2-0 -61.73810 -29.38835 -68.81250 -63.81522
## 2-1 -63.26087 -38.02020 -59.42391 -51.30303
## 2-10 -65.62353 -46.62626 -67.95604 -53.81553
## 2-11 -68.17857 -50.48936 -66.21277 -48.89899
## 2-12 -72.96000 -40.75258 -62.73684 -38.79464
## 2-13 -73.10680 -47.81308 -70.12222 -42.67308
## 2-2 -58.94118 -36.29126 -71.55056 -56.18391
## 2-3 -66.10843 -38.18447 -60.73256 -54.72727
## 2-4 -57.89610 -46.92593 -60.38554 -53.05263
## 2-5 -62.03448 -41.93636 -61.12500 -64.35556
## 2-6 -62.31461 -41.50000 -57.52874 -52.36634
## 2-7 -61.34831 -47.67677 -51.53750 -54.85057
## 2-8 -63.43478 -50.68000 -53.29897 -53.22330
## 2-9 -67.81553 -47.71910 -60.04762 -45.09091
## 20-3 -48.14286 -55.88421 -54.57292 -71.79487
## 20-7 -56.96591 -60.67708 -50.55435 -73.88889
## 20-8 -54.04651 -60.24468 -41.46988 -68.80220
## 21-3 -46.08247 -60.09474 -54.46875 -74.28261
## 21-4 -45.79787 -60.59406 -58.21277 -76.83721
## 21-5 -49.15730 -68.94382 -50.55102 -77.31313
## 21-6 -49.07292 -66.96842 -43.07368 -74.86420
## 21-7 -54.13830 -57.54167 -46.27103 -69.28736
## 21-8 -58.48421 -63.74528 -50.35052 -73.14286
## 22-3 -50.21875 -61.60952 -49.83838 -72.40698
## 22-4 -51.75000 -58.37500 -54.30928 -75.25000
## 22-5 -50.92391 -67.78723 -51.75824 -80.33333
## 22-6 -51.35484 -66.23158 -41.54082 -73.27835
## 22-7 -54.52174 -63.21505 -45.09890 -67.66250
## 22-8 -60.52525 -70.88542 -51.27778 -72.48000
## 23-3 -45.81928 -66.25532 -48.52222 -77.44186
## 23-4 -52.38947 -58.48000 -55.29787 -76.12903
## 23-5 -52.57447 -65.51579 -50.37143 -80.68966
## 23-6 -49.50505 -63.45455 -49.30693 -75.57143
## 23-7 -56.17241 -64.21154 -52.66316 -76.72941
## 23-8 -50.79787 -63.04545 -43.51042 -71.98810
## 24-3 -47.75532 -59.96939 -51.56383 -79.06667
## 24-4 -47.61111 -63.79817 -54.06593 -72.01042
## 24-5 -48.40816 -61.61702 -58.64211 -77.96000
## 24-6 -52.69231 -66.44681 -51.20879 -79.73418
## 24-7 -59.05376 -63.63529 -46.13402 -68.40625
## 24-8 -50.87356 -59.90000 -41.20619 -71.52941
## 25-3 -51.41237 -62.30769 -51.82178 -77.17045
## 25-4 -47.51087 -69.13542 -57.07778 -78.20833
## 25-7 -54.28889 -69.31373 -50.78261 -80.22500
## 25-8 -55.98958 -65.75926 -47.15000 -76.07229
## 26-3 -53.43820 -61.01205 -46.75238 -77.78652
## 26-4 -49.25490 -62.07292 -52.24272 -71.56701
## 26-5 -54.42553 -65.22917 -55.21111 -76.41379
## 26-6 -56.33721 -68.87234 -52.65882 -79.24675
## 26-7 -51.52688 -69.59341 -46.96703 -69.63736
## 26-8 -51.91262 -67.56250 -43.34343 -74.56522
## 27-3 -40.75904 -66.73636 -51.08421 -78.20000
## 27-7 -51.97849 -70.46809 -41.20225 -77.82828
## 27-8 -49.16495 -67.03191 -48.47312 -75.91667
## 28-3 -43.31250 -61.76744 -45.69159 -81.94253
## 28-7 -49.19388 -66.81132 -43.70213 -78.97802
## 28-8 -46.09091 -70.92708 -45.98889 -77.04255
## 29-3 -41.86170 -63.83333 -50.74444 -74.50000
## 29-7 -52.58824 -65.61818 -42.95556 -77.81333
## 29-8 -48.49398 -69.39604 -51.09184 -78.75000
## 3-3 -53.24419 -49.45045 -61.30000 -60.94792
## 3-7 -60.02353 -51.32258 -54.00000 -47.73684
## 3-8 -66.16883 -48.22449 -60.13793 -49.54286
## 30-3 -40.26596 -62.90217 -47.96552 -74.47191
## 30-7 -45.15534 -67.89583 -37.04545 -76.83516
## 30-8 -48.20619 -67.79412 -39.89583 -79.85714
## 31-3 -43.11628 -62.61905 -39.26804 -80.33333
## 31-7 -39.61111 -73.25000 -36.51579 -82.22826
## 31-8 -46.11340 -68.77778 -39.34021 -76.76543
## 32-3 -45.58333 -63.75269 -50.23333 -75.41237
## 32-4 -46.63158 -65.58163 -48.20000 -74.42529
## 32-5 -46.14141 -65.62500 -39.69767 -77.68085
## 32-6 -45.06000 -75.03810 -47.13793 -83.11000
## 32-7 -47.45263 -63.14000 -40.32110 -74.72826
## 32-8 -43.70588 -68.59434 -45.88542 -77.90816
## 33-3 -46.56250 -64.54167 -46.29293 -83.88506
## 33-4 -44.90625 -63.71591 -47.54444 -75.48454
## 33-7 -51.24742 -70.05217 -32.78261 -79.84314
## 33-8 -46.48421 -67.06452 -33.42574 -75.72917
## 4-3 -55.18293 -52.10417 -56.73333 -57.07527
## 4-7 -62.72414 -56.50476 -43.28378 -57.31959
## 4-8 -62.63218 -46.62745 -62.05495 -53.41176
## 5-3 -51.82796 -47.70526 -58.46316 -67.05063
## 5-7 -61.51648 -60.76042 -49.64130 -62.64894
## 5-8 -57.90323 -50.63265 -52.94253 -62.53922
## 6-3 -55.21111 -54.70408 -54.71084 -61.61957
## 6-7 -61.73626 -51.09184 -51.84615 -63.96739
## 6-8 -60.91304 -57.20635 -58.95122 -60.65957
## 7-3 -50.90000 -51.78571 -53.92941 -59.56044
## 7-7 -60.52273 -55.71963 -50.24419 -63.41379
## 7-8 -58.57317 -57.23684 -54.86869 -65.53191
## 8-3 -55.84524 -49.25532 -58.21875 -69.63830
## 8-7 -56.90816 -60.38235 -49.01961 -72.80000
## 8-8 -66.48352 -56.55469 -61.66667 -59.24176
## 9-3 -53.93750 -52.38776 -54.00000 -62.44318
## 9-4 -59.03529 -51.14563 -60.35556 -69.69048
## 9-7 -58.51613 -60.74157 -52.06186 -62.84444
## 9-8 -59.73684 -58.54545 -55.97802 -67.37079
# First Fold (validation)
onlineFold = subset(onlineCVSummary, posXY %in% permuteLocs[ , 1])
head(onlineFold)
## posXY posX posY orientation angle 00:0f:a3:39:dd:cd 00:14:bf:3b:c7:c6
## 1-12 1-12 1 12 359.9 0 -71.78182 -67.88785
## 1-8 1-8 1 8 270.2 270 -69.76364 -65.55435
## 10-8 10-8 10 8 135.1 135 -61.20909 -57.16327
## 11-3 11-3 11 3 359.9 0 -63.09910 -54.42857
## 13-8 13-8 13 8 90.3 90 -65.99115 -57.77174
## 14-7 14-7 14 7 180.2 180 -69.66972 -58.02273
## 00:14:bf:b1:97:81 00:14:bf:b1:97:8a 00:14:bf:b1:97:8d 00:14:bf:b1:97:90
## 1-12 -71.93617 -42.65979 -63.21978 -44.97872
## 1-8 -59.13793 -50.12766 -49.57143 -55.23469
## 10-8 -59.56122 -58.85149 -53.18000 -67.21429
## 11-3 -53.75000 -52.00926 -62.31707 -70.51685
## 13-8 -62.31313 -58.43000 -53.05495 -64.02198
## 14-7 -57.19318 -58.09278 -37.25000 -67.87209
# First Fold (Train)
offlineFold = subset(offline, posXY %in% permuteLocs[ , -1])
head(offlineFold)
## time posX posY orientation mac signal channel type
## 1 1.139643e+12 0 0 0 00:14:bf:b1:97:8a -38 2437000000 3
## 2 1.139643e+12 0 0 0 00:14:bf:b1:97:90 -56 2427000000 3
## 4 1.139643e+12 0 0 0 00:14:bf:b1:97:8d -65 2442000000 3
## 5 1.139643e+12 0 0 0 00:14:bf:b1:97:81 -65 2422000000 3
## 6 1.139643e+12 0 0 0 00:14:bf:3b:c7:c6 -66 2432000000 3
## 7 1.139643e+12 0 0 0 00:0f:a3:39:dd:cd -75 2412000000 3
## angle posXY
## 1 0 0-0
## 2 0 0-0
## 4 0 0-0
## 5 0 0-0
## 6 0 0-0
## 7 0 0-0
estFold = predXY(
newSignals = onlineFold[ , 6:(6+numMacs-1)],
newAngles = onlineFold[ , 4],
offlineFold,
numAngles = 3,
k = 3
)
actualFold = onlineFold[ , c("posX", "posY")]
calcError(estFold, actualFold)
## [1] 2.266667
Faster Cross Validation
Common Functions
#' @description Modified XY Prediction to help with faster CV for all K values at once (from 1 to K)
#' @param newSignals The Signal Values for the validation data for each observation
#' @param newAngles The Orientation of the validation data for each observation
#' @param trainData The training data to be used
#' @param numAngles Number of closest reference angles to include in the data
#' @param K Perform the prediction for num neighbors from 1 to K
#' @param weighted Whether the mean value should be weighted based on distancde or not.
#' @return A nested dataframe with num rows = number of (validation) observations and num columns = number of folds
#' Each entry in this dataframe is a vector of 2 values
#' indicating the prediction of the mean X and Y values for that obs and num neighbors
predXYallK = function(newSignals, newAngles, trainData, numAngles = 1, K = 10, weighted=FALSE){
closeXY = list(length = nrow(newSignals))
for (i in 1:nrow(newSignals)) {
trainSS = selectTrain(newAngles[i], trainData, m = numAngles)
closeXY[[i]] = findNN(
newSignal = as.numeric(newSignals[i, ]),
trainSubset = trainSS,
weighted = weighted
)
}
#' @description Returns the (un)weighted mean X and Y locations for a single observation and multiple neighor values
#' @param x Dataframe containing 5 columns
#' 1st column is the XY location (string)
#' 2nd column is the X location (float)
#' 3rd column is the Y location (float)
#' 4th column is the distance to the point under consideration (float)
#' 5th column is the inverse distance or weight (float)
#' @param K Number of nearest neighbors to use
#' @return A list of K pairs (each pair is a XY mean value for a single k)
all_K_means_single_obs = function(x, K){
# Row will contain the K mean values for k = 1 to K
rows = list()
for(k in seq(1, K)){
rows[[k]] = k_means_single_obs(x, k)
}
return(rows)
}
#' @description Returns the (un)weighted mean X and Y locations for a single observation and single value of neighbors
#' @param x Dataframe containing 5 columns
#' 1st column is the XY location (string)
#' 2nd column is the X location (float)
#' 3rd column is the Y location (float)
#' 4th column is the distance to the point under consideration (float)
#' 5th column is the inverse distance or weight (float)
#' @param k Number of nearest neighbors to use
#' @return A pair of XY mean values for k number of neighbors
k_means_single_obs = function(x, k){
weights = x[1:k, 5]
weighted_x = sum(x[1:k, 2] * weights) / sum(weights)
weighted_y = sum(x[1:k, 3] * weights) / sum(weights)
return(c(weighted_x, weighted_y))
}
# estXY = lapply(closeXY, function(x) sapply(x[ , 2:3], function(x) mean(x[1:k])))
estXY = lapply(closeXY, all_K_means_single_obs, K)
estXY = do.call("rbind", estXY)
return(estXY)
}
#' @description Returns the (un)weighted mean X and Y locations for a single observation and multiple neighor values
#' @param K Number of nearest neighbors to use (Will run Grid Search over all values from k = 1 to K)
#' @param v Number of folds to use
#' @param offline Use "as is" from script for now
#' @param onlineCVSummary Use "as is" from script for now
#' @param folds A matrix with rows = number of observations in each fold and columns = number of folds.
#' The values are the XY IDs to be included in that fold
#' @param numAngles Number of closest reference angles to include in the data
#' @param weighted Whether the mean value should be weighted based on distancde or not.
#' @return A vector of K values indicating the Error for each value of k from 1 to K
run_kfold = function(K, v, offline, onlineCVSummary, folds, numAngles, weighted=FALSE){
err= rep(0, K)
errCV = rep(0, K)
allErr = data.frame()
for (j in 1:v) {
print(paste("Running Fold: ", j))
onlineFold = subset(onlineCVSummary, posXY %in% folds[ , j])
offlineFold = subset(offline, posXY %in% folds[ , -j])
actualFold = onlineFold[ , c("posX", "posY")]
estFold = predXYallK(
newSignals = onlineFold[ , 6:(6+numMacs-1)],
newAngles = onlineFold[ , 4],
trainData = offlineFold,
numAngles = numAngles,
K = K,
weighted=weighted
)
# Reformat into correct format for each 'k' value
for(k in 1:K){
estSingleK = data.frame()
for(i in seq(1, length(estFold)/K)){ # i = NUmber of the observtion
estSingleK = rbind(estSingleK, t(as.data.frame(estFold[i,k])))
}
err[k] = err[k] + calcError(estSingleK, actualFold)
errCV[k] = calcError(estSingleK, actualFold) #returning all folds
}
allErr=rbind(allErr,data.frame('fold'=j, 'numNeighbors' = 1:K,'errValue' = errCV))
}
return(list(err=err,allErr=allErr))
}
Parallel CV and Plot
get_CV = function(K,v,offline,onlineCVSummary,permuteLocs,numAngles,weighted = TRUE){
library(foreach)
library(progress)
library(doParallel)
library(doSNOW)
cl <- makeCluster(detectCores())
doSNOW::registerDoSNOW(cl)
allErrors = data.frame()
start = proc.time()
pb <- progress::progress_bar$new(total = length(allAngles),format='[:bar] :percent :eta')
progress <- function(n) pb$tick()
allErrorsCV = foreach(numAngles = allAngles
,.combine = rbind
,.options.snow = list(progress=progress)
,.export = c('run_kfold','predXYallK','reshapeSS','findNN','calcError'
,'numMacs','selectTrain','roundOrientation','DIST_METHOD'
,'weightFormula')
) %dopar% {
print(paste("Running ", v, "-fold cross validation with 1 to ", K, " neighbors, for number of Angles = ", numAngles))
err = run_kfold(
K = K,
v = v,
offline = offline,
onlineCVSummary = onlineCVSummary,
folds = permuteLocs,
numAngles = numAngles,
weighted = weighted
)
err$allErr$numAngles = numAngles
return(err$allErr)
#return(data.frame(t(err)))
}
stopCluster(cl)
stop = proc.time()
diff = stop-start
print(diff)
return(allErrorsCV)
}
find_best = function(allErrorsCV){
library('caret')
library(tidyverse)
allErrors = allErrorsCV %>%
group_by(numAngles,numNeighbors) %>%
dplyr::summarise(errValue = mean(errValue)) %>%
ungroup() %>%
mutate(errValueSD=sd(errValue)
,best=FALSE
,oneSE=FALSE)
allErrors[best(as.data.frame(allErrors),"errValue",maximize=FALSE),]$best=TRUE
allErrors[oneSE(as.data.frame(allErrors),"errValue",maximize=FALSE,num=30),]$oneSE=TRUE
return(allErrors)
}
plot_best = function(allErrors) {
p = ggplot(allErrors, aes(x=numNeighbors, y=numAngles, fill= errValue
, text=paste0("A:",numAngles," N:",numNeighbors,errMethod," :", round(errValue,3)))) +
geom_tile() +
scale_y_continuous(breaks=allAngles) +
#scale_fill_distiller(palette = "RdYlBu") +
scale_fill_gradient2(low = "green",mid='darkorange', high = "darkred", na.value = NA
,midpoint=mean(c(max(allErrors$errValue),min(allErrors$errValue)))
#,midpoint=median(Errors$errValue)
)+
#scale_fill_distiller(palette = "Blues",direction=0) +
geom_text(data=allErrors[allErrors$best,],label='Best',size=3,nudge_y=.27) +
geom_text(data=allErrors[allErrors$oneSE,],label='1SE',size=3)
#p
ggplotly(p, tooltip="text")
}
Unweighted
allErrorsCV = get_CV(K=K,v=v
,offline=offline,onlineCVSummary=onlineCVSummary
,permuteLocs=permuteLocs,numAngles=numAngles
,weighted = FALSE)
##
## Attaching package: 'foreach'
## The following objects are masked from 'package:purrr':
##
## accumulate, when
## Loading required package: iterators
## Loading required package: parallel
## Loading required package: snow
##
## Attaching package: 'snow'
## The following objects are masked from 'package:parallel':
##
## clusterApply, clusterApplyLB, clusterCall, clusterEvalQ,
## clusterExport, clusterMap, clusterSplit, makeCluster, parApply,
## parCapply, parLapply, parRapply, parSapply, splitIndices,
## stopCluster
## user system elapsed
## 3.91 3.62 233.86
allErrors = find_best(allErrorsCV)
## Loading required package: lattice
##
## Attaching package: 'caret'
## The following object is masked from 'package:purrr':
##
## lift
## `summarise()` regrouping output by 'numAngles' (override with `.groups` argument)
allErrors
## # A tibble: 160 x 6
## numAngles numNeighbors errValue errValueSD best oneSE
## <int> <int> <dbl> <dbl> <lgl> <lgl>
## 1 1 1 3.42 0.200 FALSE FALSE
## 2 1 2 2.97 0.200 FALSE FALSE
## 3 1 3 2.80 0.200 FALSE FALSE
## 4 1 4 2.88 0.200 FALSE FALSE
## 5 1 5 2.77 0.200 FALSE FALSE
## 6 1 6 2.82 0.200 FALSE FALSE
## 7 1 7 2.83 0.200 FALSE FALSE
## 8 1 8 2.88 0.200 FALSE FALSE
## 9 1 9 2.87 0.200 FALSE FALSE
## 10 1 10 2.90 0.200 FALSE FALSE
## # ... with 150 more rows
print(filter(allErrors,best | oneSE))
## # A tibble: 1 x 6
## numAngles numNeighbors errValue errValueSD best oneSE
## <int> <int> <dbl> <dbl> <lgl> <lgl>
## 1 6 4 2.47 0.200 TRUE TRUE
plot_best(allErrors)
Final Model
final = filter(allErrors,oneSE)
finalAngle = final$numAngles
finalK = final$numNeighbors
finalAngle
## [1] 6
finalK
## [1] 4
#
# final = which(allErrors == min(allErrors), arr.ind = TRUE)
#
#
# finalAngleIndex = final[1]
# finalKIndex = final[2]
# finalAngle = allAngles[finalAngleIndex]
# finalK = allNeighbors[finalKIndex]
#
# finalAngle
# finalK
actualXY = onlineSummary %>% dplyr::select(posX, posY)
estXYfinalK = predXY(
newSignals = onlineSummary[ , 6:(6+numMacs-1)],
newAngles = onlineSummary[ , 4],
trainData = offline,
numAngles = finalAngle,
k = finalK,
weighted = FALSE
)
calcError(estXYfinalK, actualXY)
## [1] 2.276667
Weighted
allErrorsCVW = get_CV(K=K,v=v
,offline=offline,onlineCVSummary=onlineCVSummary
,permuteLocs=permuteLocs,numAngles=numAngles
,weighted = TRUE)
## user system elapsed
## 3.94 3.57 208.52
allErrorsW = find_best(allErrorsCVW)
## `summarise()` regrouping output by 'numAngles' (override with `.groups` argument)
allErrorsW
## # A tibble: 160 x 6
## numAngles numNeighbors errValue errValueSD best oneSE
## <int> <int> <dbl> <dbl> <lgl> <lgl>
## 1 1 1 3.42 0.146 FALSE FALSE
## 2 1 2 2.98 0.146 FALSE FALSE
## 3 1 3 2.82 0.146 FALSE FALSE
## 4 1 4 2.82 0.146 FALSE FALSE
## 5 1 5 2.69 0.146 FALSE FALSE
## 6 1 6 2.72 0.146 FALSE FALSE
## 7 1 7 2.72 0.146 FALSE FALSE
## 8 1 8 2.75 0.146 FALSE FALSE
## 9 1 9 2.73 0.146 FALSE FALSE
## 10 1 10 2.76 0.146 FALSE FALSE
## # ... with 150 more rows
print(filter(allErrorsW,best | oneSE))
## # A tibble: 1 x 6
## numAngles numNeighbors errValue errValueSD best oneSE
## <int> <int> <dbl> <dbl> <lgl> <lgl>
## 1 6 4 2.48 0.146 TRUE TRUE
plot_best(allErrorsW)
Final Model
finalW = filter(allErrorsW,oneSE)
finalAngleW = final$numAngles
finalKW = final$numNeighbors
finalAngleW
## [1] 6
finalKW
## [1] 4
actualXY = onlineSummary %>% dplyr::select(posX, posY)
estXYfinalKW = predXY(
newSignals = onlineSummary[ , 6:(6+numMacs-1)],
newAngles = onlineSummary[ , 4],
trainData = offline,
numAngles = finalAngleW,
k = finalKW,
weighted = TRUE
)
calcError(estXYfinalKW, actualXY)
## [1] 2.278147